//Simple Linked Queue 链式结构
/**
 * 说明：将流程的节点连线
 * 用法：
var queue = new Queue();


 var n = new LinkData( 5,2 );
 queue.Enqueue(n);

 var n = new LinkData( 2,3 );
 queue.Enqueue(n);

 queue.end();
 while(queue.size != 0){
    var n = queue.Dequeue();
    document.write("<br>dog's from: " +  n.id + " ," + n.next_step_id + " ");
}
 * @param newObj
 * @constructor
 */
var LinkData = function( id , next_step_id , sort ){//原始节点数据,from , to
    this.id = null;
    this.before_step_id = null ;
    this.next_step_id = null;
    this.sort = null ;
    //构造函数 intialize this.data
    this.Init = function(id,next_step_id , sort ){
        this.id = id;
        this.next_step_id = next_step_id;
        this.sort = sort;
    };
    this.Init(id,next_step_id , sort );
}
var LinkNode = function(newObj){//队列内部的链表节点
    this.obj = null;
    this.next = null;
    this.before = null;
    this.Init = function(newObj){
        this.obj = newObj;
    }
    this.Init(newObj);
}
//队列
var FlowLink = function(){
    this.front = null;//顶部
    this.rear = null;//尾部
    this.size = 0;
    this.expectSize = 0 ;

    this.MakeEmpty = function(){
        if(this.size == 0)
            return null;
        while(this.front != this.rear){
            var curQNode = this.front;
            curQNode = null;
            this.size -= 1;
            this.front = this.front.next;
        }
        this.size -= 1;
        this.front = null;
        this.rear = null;
    }
    //给一个流程节点数组，重新连接
    this.redo = function( list , isRedo ){
        var queue = new FlowLink();
        for( var i = 0 ; i < list.length ; i++ ){
            queue.Enqueue( list[i] , isRedo );
        }
        queue.sort( isRedo );
        if( queue.size > 1 ){
            this.front = queue.front;
            this.size = queue.size;
        }
    }
    //结束流程处理，检查得到的队列的长度，如果长度为1，可能该节点是独立节点，redo重新遍历一次
    //成功返回 rs对象 ，通过id可以获取
    this.sort = function( redoCount ){
        if( !redoCount ) redoCount = 1 ;
        this.toAdd = this.check( this.toAdd );
        if( this.size == 1 && this.toAdd.length > this.size && redoCount < 3 ){
            console.log('flow only 1 node , redo ');
            this.toAdd.push( this.front.obj );
            this.redo( this.toAdd , redoCount + 1 );
        }
        var rs = {};
        var index = 0 ;
        var beforeNode ;
        while(this.size != 0){
            index += 1 ;
            var n = this.Dequeue();
            n.sort = index;
            rs[ n.id ] = n;
        }
        //连接信息的最后节点，需要单独处理
        if( this.rear && this.rear.obj.next_step_id ){
            var n = new LinkData( this.rear.obj.next_step_id , null , ++index );
            n.before_step_id =  this.rear.obj.id ;
            rs [ n.id ] = n;
            this.rear = new LinkNode(n);
        }

        return rs;
    };
    //检查未连成线的节点，重新进入队列连线
    this.check = function ( toAdd ){
        var nextToAdd = [];
        for( var i = 0 ; i <  toAdd.length ; i++){
            var rs = this.link( new LinkNode( toAdd[i]) );
            if( !rs ){
                nextToAdd.push( toAdd[i] );
            }
        }
        if( nextToAdd.length > 0  && toAdd.length != nextToAdd.length ){
            return this.check( nextToAdd );
        }
        return nextToAdd;
    };

    this.toAdd = [];//未能连成线的

    //返回是否全部连接
    this.isOk = function( expect ){
        return this.expectSize  == (expect - 1 ) ;
    }

    this.Enqueue = function(newObj , isRedo ){
        if( !isRedo ){
            this.expectSize += 1;
        }
        var rs = this.link( new LinkNode(newObj) );
        if( !rs ){
            this.toAdd.push(newObj);//加入未找到队列
        }
    };

    //连接队列，连接不上返回
    this.link = function( node ){
        if( this.front == null ){
            this.front = node ;
            this.rear = node ;
            this.size+=1;
            return true;
        }else{
            var cur = this.front;
            var tail = this.rear;
            if( node.obj.next_step_id == cur.obj.id ) {
                node.next = cur ;
                cur.before = node;
                //赋值cur节点的上个节点before_step_id
                cur.obj.before_step_id = node.obj.id ;
                this.front = node;
                this.size+=1;
                return true;
            }
            if( tail.obj.next_step_id == node.obj.id ) {
                //赋值node的上级id为tail的id
                node.obj.before_step_id = tail.obj.id ;
                tail.next = node ;
                this.rear = node;
                this.size+=1;
                return true;
            }
            return false;
        }
    };
    this.Dequeue = function(){
        if(this.size <= 0)
            return null;
        else{
            this.size -= 1;
            var curQNode = this.front;
            this.front = this.front.next;
            return curQNode.obj;
        }
    };

}